package com.heima.comment.service.impl;

import com.heima.comment.feign.UserFeign;
import com.heima.comment.service.ApCommentService;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @作者 itcast
 * @创建日期 2020/10/9 14:29
 **/
@Service
@Transactional
public class ApCommentServiceImpl implements ApCommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    MongoTemplate mongoTemplate;
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1. 校验参数
        if(dto == null || dto.getArticleId() == null || StringUtils.isEmpty(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getContent().length() > 140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论字数不能大于140字");
        }
        //2. 校验是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if(user == null || user.getId() == 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"请登录后再评论");
        }
        //3. 远程用户微服务获取登录用户信息
        ApUser apUser = userFeign.findApUserById(user.getId());
        if(apUser == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"用户信息错误");
        }
        //4. 封装评论信息
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setContent(dto.getContent());
        apComment.setEntryId(dto.getArticleId());
        apComment.setImage(user.getImage());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short)0);
        apComment.setFlag((short)0);
        //5  保存评论信息
        mongoTemplate.insert(apComment);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1. 检查参数
        if(dto.getCommentId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2. 判断用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if(user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3  根据评论ID查询评论信息
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(apComment == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //4. 点赞操作
        int likes = apComment.getLikes();
        if(dto.getOperation() == 0){
            //   4.1 点赞数+1
            apComment.setLikes(likes+1);
            mongoTemplate.save(apComment);
            // 应该判断下是否已经点过赞

            //   4.2 评论点赞表添加点赞行为数据
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(user.getId());
            apCommentLike.setCommentId(dto.getCommentId());
            mongoTemplate.save(apCommentLike);
        }else if (dto.getOperation()==1){
        //5. 取消点赞
            //   5.1 点赞数-1
            apComment.setLikes(likes< 1 ? 0 : likes-1);
            mongoTemplate.save(apComment);
            //   5.2 删除点赞行为数据
            mongoTemplate.remove(Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId())),ApCommentLike.class);
        }
        //6. 数据返回 返回点赞数量
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("likes",likes);
        return ResponseResult.okResult(resultMap);
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //1. 检查参数
        if(dto.getArticleId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getSize() == null || dto.getSize() == 0){
            dto.setSize(20);
        }
        //2. 按照文章ID过滤，设置分页和排序
        Criteria criteria = Criteria.where("entryId").is(dto.getArticleId());
        if(dto.getMinLikes()!=null){
            criteria.and("likes").lt(dto.getMinLikes());
        }
        Query query = Query.query(criteria);
        query.limit(dto.getSize());
        query.with(Sort.by(Sort.Direction.DESC,"likes"));
        // 查询评论集合
        List<ApComment> list = mongoTemplate.find(query, ApComment.class);
        //3. 数据封装返回
        //3.1 用户未登录 加载数据
        ApUser user = AppThreadLocalUtils.getUser();
        // 如果用户未登录，直接返回查询到的集合数据
        if (user==null) {
            return ResponseResult.okResult(list);
        }
        //3.2 用户已登录，加载数据，需要判断当前用户点赞了哪些评论
        if(list!=null){
            List<String> idList = list.stream().map(ApComment::getId).collect(Collectors.toList());
            // 查询点赞行为中是否有该登录用户的点赞数据
            Query commentLikeQuery = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").in(idList));
            List<ApCommentLike> apCommentLikes = mongoTemplate.find(commentLikeQuery, ApCommentLike.class);
            if(apCommentLikes!=null&&!apCommentLikes.isEmpty()){
                // 将每一个点赞行为 添加到对应评论中
                Set<String> collectArticleIds = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toSet());
                List<ApCommentVo> apCommentVoList = new ArrayList<>();
                try {
                    for (ApComment apComment : list){
                        ApCommentVo apCommentVo = new ApCommentVo();
                        BeanUtils.copyProperties(apCommentVo,apComment);
                        // 判断是否点赞过
                        if(collectArticleIds.contains(apComment.getId())){
                            apCommentVo.setOperation(((short) 0));
                        }
                        apCommentVoList.add(apCommentVo);
                    }
                    return ResponseResult.okResult(apCommentVoList); // 添加了点赞行为的评论列表
                } catch (Exception e) {
                    e.printStackTrace();
                    return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
                }
            }
        }
        return ResponseResult.okResult(list);
    }
}
